home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / vga / _vgadraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  18.9 KB  |  965 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  _vgadraw.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. /* basic graphic routines of libWx  declared in <LEDA/impl/x_basic.h>) 
  17.  * iplemented for MSDOS using the VGA 640x480x16 color graphics mode
  18.  */
  19.  
  20. #include "vga.h"
  21. #include "vgafont"
  22.  
  23. static VIDEO_PTR video_buf;
  24. static int COLOR = 1;
  25. static int MODE  = 0;
  26. static int LINEWIDTH = 1;
  27. static int LINESTYLE = 0;
  28.  
  29.  
  30. void flush_display() {}
  31.  
  32. int  new_color(const char*) { return 1; }
  33.  
  34. int  text_height(const char*)  { return FONT_HEIGHT; }
  35. int  text_width(const char* s) { return FONT_WIDTH*strlen(s); }
  36.  
  37. int load_text_font(const char*) { return 0;}
  38. int load_bold_font(const char*) { return 0;}
  39. int load_message_font(const char*) { return 0;}
  40.  
  41. int  set_font(const char*) { return 0;}
  42. void set_text_font() {}
  43. void set_bold_font() {}
  44. void set_message_font() {}
  45.  
  46. int set_line_width(int width)
  47. { int save = LINEWIDTH;
  48.   LINEWIDTH = width;
  49.   return save;
  50. }
  51.  
  52. int set_line_style(int style)
  53. { int save = LINESTYLE;
  54.   LINESTYLE = style;
  55.   return save;
  56. }
  57.  
  58. int set_color(int color)
  59. {  int save = COLOR;
  60.    COLOR = color;
  61.    port_out(0x00, GRA_I );
  62.    port_out(color, GRA_D );
  63.    return save;
  64.  }
  65.  
  66. int set_mode(int mode)
  67. { int save = MODE;
  68.  
  69.   MODE = mode;
  70.  
  71.   if (mode==1)         mode = 3; /* xor */
  72.   else if (mode==2)    mode = 2; /* or  */
  73.      else if (mode==3) mode = 1; /* and */
  74.                   else mode = 0; /* src */
  75.  
  76.   port_out(0x03, GRA_I );
  77.   port_out(mode<<3, GRA_D );
  78.   return save;
  79. }
  80.  
  81.  
  82. static void put_pixel(VgaWindow win, int x, int y)
  83. { VIDEO_PTR p;
  84.  
  85.   if (x < 0 || x >= win->width || y < 0 || y >= win->height) return;
  86.  
  87.   x += win->xpos;
  88.   y += win->ypos;
  89.  
  90.   if (VIDEO==0)   /* write into (monochrome) buffer */
  91.      video_buf[y*LINE_BYTES+(x>>3)] |= (0x80 >> (x & 7));
  92.   else
  93.   { p = VIDEO + y*LINE_BYTES + (x>>3);
  94.     port_out(8, GRA_I);
  95.     port_out((0x80 >> (x & 7)), GRA_D);
  96.     *p = *p;
  97.    }
  98. }
  99.  
  100. static void vline(VgaWindow win,int x, int y0, int y1)
  101. { register VIDEO_PTR p;
  102.   register VIDEO_PTR last;
  103.  
  104.   if (y0 > y1)
  105.   { int y = y0;
  106.     y0 = y1;
  107.     y1 = y;
  108.    }
  109.  
  110.   if (x < 0 || x >= win->width || y1 < 0 || y0 >= win->height) return;
  111.  
  112.   if (y0 < 0) y0 = 0;
  113.   if (y1 >= win->height) y1 = win->height-1;
  114.  
  115.   x  += win->xpos;
  116.   y0 += win->ypos;
  117.   y1 += win->ypos;
  118.  
  119.   port_out(8, GRA_I);
  120.   port_out(128 >> (x&7), GRA_D);
  121.   last  = VIDEO + LINE_BYTES*y1 + (x>>3);
  122.   for(p = VIDEO + LINE_BYTES*y0 + (x>>3); p <= last; p+=LINE_BYTES)  *p = *p;
  123.  
  124. }
  125.  
  126.  
  127. static void hline(VgaWindow win, int x0, int x1, int y)
  128. { register VIDEO_PTR p;
  129.   register VIDEO_PTR first;
  130.   register VIDEO_PTR last;
  131.   char byte;
  132.  
  133.   if (x0 > x1)
  134.   { int x = x0;
  135.     x0 = x1;
  136.     x1 = x;
  137.    }
  138.   if (y < 0 || y >= win->height || x1 < 0 || x0 >= win->width) return;
  139.   if (x0 < 0) x0 = 0;
  140.   if (x1 >= win->width) x1 = win->width-1;
  141.  
  142.   x0 += win->xpos;
  143.   x1 += win->xpos;
  144.   y  += win->ypos;
  145.  
  146.  
  147.   if (x0 > DISP_MAX_X  || y > DISP_MAX_Y || y < 0) return;
  148.  
  149.   if (x1 > DISP_MAX_X) x1 = DISP_MAX_X;
  150.   if (x0 < 0) x0 = 0;
  151.  
  152.   first = VIDEO + LINE_BYTES*y + (x0>>3);
  153.   last  = VIDEO + LINE_BYTES*y + (x1>>3);
  154.  
  155.   port_out(8, GRA_I);
  156.  
  157.   if (first == last)
  158.   { byte  = 0xFF>>(x0&7);
  159.     byte &= 0xFF<<((~x1)&7);
  160.     port_out(byte, GRA_D);
  161.     *first = *first;
  162.     return;
  163.    }
  164.  
  165.   port_out(0xFF>>(x0&7), GRA_D);
  166.   *first = *first;
  167.  
  168.   port_out(0xFF<<((~x1)&7), GRA_D);
  169.   *last = *last;
  170.  
  171.   port_out(0xFF, GRA_D);
  172.   for(p=first+1; p<last; p++) *p = *p;
  173.  
  174.  }
  175.  
  176.  
  177. static void Draw_Line(VgaWindow win, int x1, int y1, int x2, int y2)
  178. {
  179.   register int sy = 1;
  180.   register int dx = x2 - x1;
  181.   register int dy = y2 - y1;
  182.   register int c;
  183.   int i;
  184.  
  185.   if (dx < 0)
  186.   { int i = x1;
  187.     x1 = x2;
  188.     x2 = i;
  189.     dx = -dx;
  190.     i = y1;
  191.     y1 = y2;
  192.     y2 = i;
  193.     dy = -dy;
  194.    }
  195.   if (dy < 0)
  196.   { dy = -dy;
  197.     sy = -1;
  198.    }
  199.  
  200.   if (dx > dy)
  201.   { c = dx / 2;
  202.     put_pixel(win,x1,y1);
  203.     for (i=1; i<=LINEWIDTH/2; i++)
  204.     { put_pixel(win,x1,y1+i);
  205.       put_pixel(win,x1,y1-i);
  206.      }
  207.     while(x1 != x2)
  208.     { x1++;
  209.       c += dy;
  210.       if (c >= dx)
  211.       { c -= dx;
  212.         y1 += sy;
  213.        }
  214.       put_pixel(win,x1,y1);
  215.       for (i=1; i<=LINEWIDTH/2; i++)
  216.       { put_pixel(win,x1,y1+i);
  217.         put_pixel(win,x1,y1-i);
  218.        }
  219.     }
  220.   }
  221.   else
  222.   { c = dy / 2;
  223.     put_pixel(win,x1,y1);
  224.     for (i=1; i<=LINEWIDTH/2; i++)
  225.     { put_pixel(win,x1+i,y1);
  226.       put_pixel(win,x1-i,y1);
  227.      }
  228.     while(y1 != y2)
  229.     { y1 += sy;
  230.       c += dx;
  231.       if (c >= dy)
  232.       { c -= dy;
  233.         x1++;
  234.        }
  235.       put_pixel(win,x1,y1);
  236.       for (i=1; i<=LINEWIDTH/2; i++)
  237.       { put_pixel(win,x1+i,y1);
  238.         put_pixel(win,x1-i,y1);
  239.        }
  240.     }
  241.   }
  242. }
  243.  
  244. void line(Window w, int x1, int y1, int x2, int y2)
  245. { int i;
  246.  
  247.   VgaWindow win = win_stack[w];
  248.  
  249.   if (x1 == x2)
  250.   { vline(win,x1,y1,y2);
  251.     for (i=1; i<=LINEWIDTH/2; i++)
  252.     { vline(win,x1-i,y1,y2);
  253.       vline(win,x1+i,y1,y2);
  254.      }
  255.     return;
  256.    }
  257.  
  258.   if (y1 == y2)
  259.   { hline(win,x1,x2,y1);
  260.     for (i=1; i<=LINEWIDTH/2; i++)
  261.     { hline(win,x1,x2,y1-i);
  262.       hline(win,x1,x2,y1+i);
  263.      }
  264.     return;
  265.    }
  266.  
  267.   Draw_Line(win,x1,y1,x2,y2);
  268. }
  269.  
  270.  
  271.  
  272. static int get_pixel(int x, int y)
  273. {
  274.   register int bit = 0x80 >> (x&7);
  275.   register VIDEO_PTR byte = VIDEO + LINE_BYTES*y+(x>>3);
  276.   register int c;
  277.  
  278.   if (x < 0 || x > DISP_MAX_X || y < 0 || y > DISP_MAX_Y) return 0;
  279.  
  280.   /* set read mode 1 */
  281.   port_out(5, GRA_I);
  282.   port_out(8, GRA_D);
  283.  
  284.   for(c=0; c<16; c++)
  285.   { port_out(2, GRA_I);
  286.     port_out(c, GRA_D);
  287.     if (*byte & bit)  break;
  288.    }
  289.  
  290.   return c;
  291. }
  292.  
  293.  
  294. #define FILLPUT(pos,byte)\
  295. { p = pos;\
  296.   if ((*p & (byte)) == 0)\
  297.   { *p |= (byte);\
  298.     POS[top] = p; \
  299.     BYTE[top] = byte; \
  300.     top = (top+1) % 512; } else;\
  301. }
  302.  
  303. static  VIDEO_PTR      POS[512];
  304. static  unsigned char  BYTE[512];
  305.  
  306. static void fill_bits(VIDEO_PTR pos,unsigned char byte)
  307. { register int bot = 0;
  308.   register int top = 0;
  309.   register VIDEO_PTR p;
  310.  
  311.   FILLPUT(pos,byte)
  312.  
  313.   while (top != bot)
  314.   { pos  = POS[bot];
  315.     byte = BYTE[bot];
  316.  
  317.     bot = (bot+1) % 512;
  318.  
  319.     if (byte == 128)
  320.        FILLPUT(pos-1,1)
  321.     else
  322.        FILLPUT(pos,byte<<1)
  323.  
  324.     if (byte == 1)
  325.        FILLPUT(pos+1,128)
  326.     else
  327.        FILLPUT(pos,byte>>1)
  328.  
  329.     FILLPUT(pos-LINE_BYTES,byte)
  330.     FILLPUT(pos+LINE_BYTES,byte)
  331.   }
  332. }
  333.  
  334. static  VIDEO_PTR  POS1[512];
  335. static  int pos_top = 0;
  336.  
  337. void fill_bytes(VIDEO_PTR pos, int d)
  338. { VIDEO_PTR p = pos+d;
  339.  
  340.   unsigned char c = *p;
  341.   unsigned char pat = 0xFF;
  342.  
  343.   if (c == 0)
  344.   { *p = 0xFF;
  345.     fill_bytes(p,  1);
  346.     fill_bytes(p, -1);
  347.     fill_bytes(p, LINE_BYTES);
  348.     fill_bytes(p,-LINE_BYTES);
  349.     return;
  350.    }
  351.  
  352.   if (d == -1)
  353.   { while((c&1) == 0)
  354.     { pat <<= 1;
  355.       c >>= 1;
  356.      }
  357.     *p |= ~pat;
  358.    }
  359.  
  360.   if (d == 1)
  361.   { while((c&128) == 0)
  362.     { pat >>= 1;
  363.       c <<= 1;
  364.      }
  365.     *p |= ~pat;
  366.    }
  367.  
  368.   if((c&8) == 0 && (d == LINE_BYTES || d == -LINE_BYTES))   POS1[pos_top++] = p;
  369.  
  370.  }
  371.  
  372.  
  373. void fill_polygon(Window w, int n, int* xcoord, int* ycoord)
  374. {
  375.   VgaWindow win = win_stack[w];
  376.  
  377.   register VIDEO_PTR p;
  378.   register VIDEO_PTR q;
  379.   register VIDEO_PTR first;
  380.   register VIDEO_PTR first1;
  381.   register VIDEO_PTR last;
  382.  
  383.   int i,m1,m2;
  384.   int minxi = 0;
  385.   int maxxi = 0;
  386.   int minyi = 0;
  387.   int maxyi = 0;
  388.   int minx,maxx,miny,maxy,x,y;
  389.  
  390.   VIDEO_PTR video_save = VIDEO;
  391.  
  392.   VIDEO = 0;
  393.  
  394.   video_buf = (VIDEO_PTR)malloc(LINE_BYTES*480);
  395.  
  396.  
  397.   for(i=1;i<n;i++)
  398.   { minxi = (xcoord[i] < xcoord[minxi]) ? i : minxi;
  399.     minyi = (ycoord[i] < ycoord[minyi]) ? i : minyi;
  400.     maxxi = (xcoord[i] > xcoord[maxxi]) ? i : maxxi;
  401.     maxyi = (ycoord[i] > ycoord[maxyi]) ? i : maxyi;
  402.    }
  403.  
  404.   minx = (xcoord[minxi] + win->xpos)/8;
  405.   maxx = (xcoord[maxxi] + win->xpos)/8;
  406.   miny = ycoord[minyi] + win->ypos;
  407.   maxy = ycoord[maxyi] + win->ypos;
  408.  
  409.   m1 =  (minxi == 0)   ?  n-1 : minxi-1;
  410.   m2 =  (minxi == n-1) ?  0   : minxi+1;
  411.  
  412.   for(i=miny; i<=maxy; i++)
  413.   { last = video_buf+LINE_BYTES*i + maxx;
  414.     for(p=video_buf+LINE_BYTES*i+minx; p<=last; p++) *p= 0;
  415.    }
  416.  
  417.   for(i=0; i<n-1; i++)
  418.       Draw_Line(win,xcoord[i],ycoord[i],xcoord[i+1],ycoord[i+1]);
  419.  
  420.   Draw_Line(win,xcoord[0],ycoord[0],xcoord[n-1],ycoord[n-1]);
  421.  
  422.   x = (xcoord[m1] + xcoord[m2] + xcoord[minxi])/3 + win->xpos;
  423.   y = (ycoord[m1] + ycoord[m2] + ycoord[minxi])/3 + win->ypos;
  424.  
  425.   pos_top = 0;
  426.   fill_bytes(video_buf + LINE_BYTES*y + x/8,0);
  427.  
  428.   while (pos_top--) fill_bits(POS1[pos_top],8);
  429.  
  430.   fill_bits(video_buf+LINE_BYTES*y+x/8,128>>(x%8));
  431.  
  432.   VIDEO = video_save;
  433.  
  434.   first  = video_buf+LINE_BYTES*miny + minx;
  435.   first1 = VIDEO+LINE_BYTES*miny + minx;
  436.   last   = video_buf+LINE_BYTES*miny + maxx;
  437.  
  438.   port_out(8, GRA_I);
  439.  
  440.   while(miny <= maxy)
  441.   { for(p=first, q = first1; p<=last; p++, q++)
  442.     { port_out(*p, GRA_D);
  443.       *q = *q;
  444.      }
  445.     first  += LINE_BYTES;
  446.     first1 += LINE_BYTES;
  447.     last   += LINE_BYTES;
  448.     miny++;
  449.    }
  450.  
  451.   free((char*)video_buf);
  452. }
  453.  
  454.  
  455. void box(Window w, int x0, int y0, int x1, int y1)
  456. { VgaWindow win = win_stack[w];
  457.   if (y0 > y1)
  458.   { int y = y0;
  459.     y0 = y1;
  460.     y1 = y;
  461.    }
  462.   while(y0<=y1) hline(win,x0,x1,y0++);
  463.  }
  464.  
  465.  
  466. void  rectangle(Window w, int x0, int y0, int x1, int y1)
  467.   int left  = x0;
  468.   int right = x1;
  469.   int top   = y0;
  470.   int bottom= y1;
  471.  
  472.   if (x0 > x1)
  473.   { left  = x1;
  474.     right = x0;
  475.    }
  476.  
  477.   if (y0 > y1)
  478.   { top  = y1;
  479.     bottom = y0;
  480.    }
  481.  
  482.   line(w,left, top,     right,top);
  483.   line(w,left, bottom,  right,bottom);
  484.   line(w,left, bottom-1,left, top+1);
  485.   line(w,right,bottom-1,right,top+1);
  486. }
  487.  
  488.  
  489. void circle(Window w, int x0,int y0,int r0)
  490. { VgaWindow win = win_stack[w];
  491.   int r;
  492.  
  493.   for (r = r0-LINEWIDTH/2; r <= r0+LINEWIDTH/2; r++)
  494.   { int y = r;
  495.     int x = 0;
  496.     int e = 3-2*y;
  497.  
  498.     put_pixel(win,x0,y0+r);
  499.     put_pixel(win,x0,y0-r);
  500.     put_pixel(win,x0+r,y0);
  501.     put_pixel(win,x0-r,y0);
  502.  
  503.     for (x=1;x<y;)
  504.       { put_pixel(win,x0+x,y0+y);
  505.         put_pixel(win,x0+x,y0-y);
  506.         put_pixel(win,x0-x,y0+y);
  507.         put_pixel(win,x0-x,y0-y);
  508.         put_pixel(win,x0+y,y0+x);
  509.         put_pixel(win,x0+y,y0-x);
  510.         put_pixel(win,x0-y,y0+x);
  511.         put_pixel(win,x0-y,y0-x);
  512.         x++;
  513.         if (e>=0) { y--; e = e - 4*y; }
  514.         e = e + 4*x + 2;
  515.        }
  516.  
  517.     if (x == y)
  518.     { put_pixel(win,x0+x,y0+y);
  519.       put_pixel(win,x0+x,y0-y);
  520.       put_pixel(win,x0-x,y0+y);
  521.       put_pixel(win,x0-x,y0-y);
  522.      }
  523.   }
  524. }
  525.  
  526.  
  527. void fill_circle(Window w, int x0, int y0, int r)
  528. { VgaWindow win = win_stack[w];
  529.   int y = 1;
  530.   int x = r;
  531.   int e = 3-2*r;
  532.  
  533.   hline(win,x0-x,x0+x,y0);
  534.  
  535.   while (y<=x)
  536.   { hline(win,x0-x,x0+x,y0+y);
  537.     hline(win,x0-x,x0+x,y0-y);
  538.  
  539.     if (y<x && e>=0)
  540.     { hline(win,x0-y,x0+y,y0+x);
  541.       hline(win,x0-y,x0+y,y0-x);
  542.       x--;
  543.       e = e - 4*x;
  544.      }
  545.     y++;
  546.     e = e + 4*y + 2;
  547.    }
  548. }
  549.  
  550.  
  551.  
  552. static void Put_Text(VgaWindow win, int x, int y, const char *str, int bg_col)
  553. { /* bgcol = -1 : transparent */
  554.   register unsigned char *fp1;
  555.   register unsigned char *fp2;
  556.   register unsigned char c;
  557.  
  558.   register VIDEO_PTR start;
  559.   register VIDEO_PTR stop;
  560.   register VIDEO_PTR q;
  561.  
  562.   char text[128];
  563.   int dy,i;
  564.   int len = strlen(str);
  565.   int l = (win->width-x)/text_width("H");
  566.   if (len > l) len = l;
  567.   if (len > 0) strncpy(text,str,len);
  568.   text[len] = 0;
  569.  
  570.  
  571.   if (y < 0 || y >= win->height || x < 0 || x >= win->width) return;
  572.  
  573.   if (bg_col >= 0)
  574.   { int save_color = set_color(bg_col);
  575.     int save_mode = set_mode(0);
  576.     box(win->id,x,y,x+text_width(text)-1,y+text_height(text)-1);
  577.     set_mode(save_mode);
  578.     set_color(save_color);
  579.    }
  580.  
  581.   dy = win->height - y;
  582.  
  583.   if (dy > FONT_HEIGHT) dy = FONT_HEIGHT;
  584.  
  585.   x += win->xpos;
  586.   y += win->ypos;
  587.  
  588.   fp1 = FONT + FONT_HEIGHT * ' ';
  589.   fp2 = FONT + FONT_HEIGHT * (text[0] & 127);
  590.  
  591.   start = VIDEO + LINE_BYTES*y + x/8;
  592.   stop = start + LINE_BYTES*dy;
  593.  
  594.   x &= 7;
  595.  
  596.   port_out(8, GRA_I);
  597.  
  598.   for(i=0;i<len; i++)
  599.   { for (q = start; q < stop; q+=LINE_BYTES, fp1++,fp2++)
  600.     { c = ((*fp2)>>x) | ((*fp1)<<(8-x));
  601.       port_out(c, GRA_D);
  602.       *q = *q;
  603.      }
  604.     fp1 = FONT + FONT_HEIGHT * (text[i] & 127);
  605.     fp2 = FONT + FONT_HEIGHT * (text[i+1] & 127);
  606.     start++;
  607.     stop++;
  608.    }
  609.  
  610.   if (x > 0)
  611.     for (q = start; q < stop; q+=LINE_BYTES, fp1++,fp2++)
  612.     { c = (*fp1)<<(8-x);
  613.       port_out(c, GRA_D);
  614.       *q = *q;
  615.      }
  616.  
  617. }
  618.  
  619. void put_text(Window w, int x, int y, const char *text, int opaque)
  620. { VgaWindow win = win_stack[w];
  621.   Put_Text(win,x,y,text,opaque ? win->bg_col : -1); }
  622.  
  623.  
  624. void put_ctext(Window w, int x, int y, const char* str, int opaque)
  625. { put_text(w,x-(text_width(str)-1)/2, y-(text_height(str)-1)/2, str, opaque);
  626.  }
  627.  
  628.  
  629. void show_coordinates(Window w, const char* s)
  630. { VgaWindow win = win_stack[w];
  631.   int save_mode = set_mode(0);
  632.   int save_col  = set_color(4);
  633.   put_text(w,win->width-138,1,s,1); 
  634.   set_mode(save_mode);
  635.   set_color(save_col);
  636. }
  637.  
  638.  
  639. void clear_window(Window w, int c)
  640. { VgaWindow win = win_stack[w];
  641.   int save_col  = set_color(win->bg_col);
  642.   int save_mode = set_mode(0);
  643.   box(w,0,0,win->width-1,win->height-1);
  644.   set_color(save_col);
  645.   set_mode(save_mode);
  646.  }
  647.  
  648.  
  649. void pixel(Window w, int x, int y) { put_pixel(win_stack[w],x,y);}
  650.  
  651. void pixels(Window w, int n, int* x, int* y)
  652. { while(n--) put_pixel(win_stack[w],x[n],y[n]); }
  653.  
  654.  
  655.  
  656. #define put_arc_pixel(X,Y,x,y,top) { X[top] = x; Y[top] = y; top++; }
  657.  
  658. void arc(Window w, int x0, int y0, int r1, int r2, double start, double angle)
  659. { VgaWindow win = win_stack[w];
  660.   int* X = new int[10*r1];
  661.   int* Y = new int[10*r2];
  662.   int r;
  663.  
  664.  x0 += win->xpos;
  665.  y0 += win->ypos;
  666.  
  667.  if (angle < 0)
  668.  { start += angle;
  669.    angle *= -1;
  670.   }
  671.  
  672.  if (angle > 2*M_PI) angle = 2*M_PI;
  673.  
  674.  while (start < 0) start += 2*M_PI;
  675.  
  676.  for (r = r1-LINEWIDTH/2; r <= r1+LINEWIDTH/2; r++)
  677.  { int y = r;
  678.    int x = 0;
  679.    int e = 3-2*y;
  680.    int top = 0;
  681.    int high;
  682.    int high1;
  683.    int s,l;
  684.    float L;
  685.    int i;
  686.  
  687.    while (x < y)
  688.    { put_arc_pixel(X,Y,x,y,top);
  689.      x++;
  690.      if (e>=0) { y--; e -= 4*y; }
  691.      e += 4*x + 2;
  692.     }
  693.  
  694.    high = top-1;
  695.  
  696.    if (x==y) put_arc_pixel(X,Y,x,y,top);
  697.  
  698.    high1 = top;
  699.  
  700.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y, Y[i],-X[i],top);
  701.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y, X[i],-Y[i],top);
  702.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y,-X[i],-Y[i],top);
  703.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y,-Y[i],-X[i],top);
  704.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y,-Y[i], X[i],top);
  705.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y,-X[i], Y[i],top);
  706.    for(i = 0;    i < high1; i++) put_arc_pixel(X,Y, X[i], Y[i],top);
  707.    for(i = high; i > 0;     i--) put_arc_pixel(X,Y, Y[i], X[i],top);
  708.  
  709.    L = (top - high1)/(2*M_PI);
  710.    s = high1 - 1 + (int)(start*L);
  711.    l = s + (int)(angle*L);
  712.  
  713.    if (l >= top)
  714.    { for(i=s; i < top; i++) put_pixel(win,x0+X[i],y0+Y[i]);
  715.      s = high - 1;
  716.      l = s + l - top;
  717.     }
  718.    for(i=s; i < l; i++) put_pixel(win,x0+X[i],y0+Y[i]);
  719.   }
  720.  
  721.   delete X;
  722.   delete Y;
  723. }
  724.  
  725.  
  726. static void ellipse_point(VgaWindow win, int x0, int y0, int x, int y)
  727. { put_pixel(win,x0+x,y0+y);
  728.   put_pixel(win,x0-x,y0+y);
  729.   put_pixel(win,x0+x,y0-y);
  730.   put_pixel(win,x0-x,y0-y);
  731.  }
  732.  
  733.  
  734. void ellipse(Window w, int x0, int y0, int a, int b)
  735.   /* Foley, van Dam, Feiner, Huges: Computer Graphics, page 90 */
  736.  
  737.   VgaWindow win = win_stack[w];
  738.  
  739.   double d1,d2;
  740.   int x,y;
  741.   int a_2 = a*a;
  742.   int b_2 = b*b;
  743.  
  744.   put_pixel(win,x0,y0-b);
  745.   put_pixel(win,x0,y0+b);
  746.   put_pixel(win,x0-a,y0);
  747.   put_pixel(win,x0+a,y0);
  748.  
  749.   x = 0;
  750.   y = b;
  751.  
  752.   d1 = b*b + a*a*(0.25 - b); 
  753.    
  754.   while (a_2*(y - 0.5) > b_2*(x+1))
  755.   { if (d1 < 0)
  756.       d1 += b_2*(2*x + 3);
  757.     else
  758.     { d1 += b_2*(2*x + 3) + a_2*(2 - 2*y);
  759.       y--;
  760.      }
  761.     x++;
  762.     ellipse_point(win,x0,y0,x,y);
  763.   }
  764.  
  765.   d2 = b_2*(x+0.5)*(x+0.5) + a_2*(y - 1)*(y - 1) - a_2*b_2;
  766.  
  767.   while (y > 1)
  768.   { if (d2 < 0)
  769.      { d2 += b_2*(2*x+2)+a_2*(3-2*y);
  770.        x++;
  771.       }
  772.     else
  773.        d2 += a*a*(3-2*y);
  774.  
  775.     y--;
  776.  
  777.     ellipse_point(win,x0,y0,x,y);
  778.    }
  779. }
  780.  
  781.  
  782. void fill_ellipse(Window w, int x0, int y0, int a, int b)
  783. { VgaWindow win = win_stack[w];
  784.   double d1,d2;
  785.   int x,y;
  786.   int a_2 = a*a;
  787.   int b_2 = b*b;
  788.  
  789.   x = 0;
  790.   y = b;
  791.  
  792.   d1 = b*b + a*a*(0.25 - b); 
  793.    
  794.   while (a_2*(y - 0.5) > b_2*(x+1))
  795.   { if (d1 < 0)
  796.       d1 += b_2*(2*x + 3);
  797.     else
  798.     { d1 += b_2*(2*x + 3) + a_2*(2 - 2*y);
  799.       hline(win,x0-x,x0+x,y0+y);
  800.       hline(win,x0-x,x0+x,y0-y);
  801.       y--;
  802.      }
  803.     x++;
  804.   }
  805.   hline(win,x0-x,x0+x,y0+y);
  806.   hline(win,x0-x,x0+x,y0-y);
  807.  
  808.   d2 = b_2*(x+0.5)*(x+0.5) + a_2*(y - 1)*(y - 1) - a_2*b_2;
  809.  
  810.   while (y > 1)
  811.   { if (d2 < 0)
  812.      { d2 += b_2*(2*x+2)+a_2*(3-2*y);
  813.        x++;
  814.       }
  815.     else
  816.        d2 += a*a*(3-2*y);
  817.  
  818.     y--;
  819.  
  820.     hline(win,x0-x,x0+x,y0+y);
  821.     hline(win,x0-x,x0+x,y0-y);
  822.    }
  823.  
  824.   hline(win,x0-x,x0+x,y0);
  825.  
  826. }
  827.  
  828.  
  829. void fill_arc(Window,int,int,int,int,double,double)
  830. { }
  831.  
  832.  
  833. static void copy_box(int left, int top, int width, int height, int x, int y)
  834. {
  835.   register VIDEO_PTR first1;
  836.   register VIDEO_PTR first;
  837.   register VIDEO_PTR last1;
  838.   register VIDEO_PTR last;
  839.   register VIDEO_PTR p;
  840.   register VIDEO_PTR q;
  841.  
  842.   int i;
  843.  
  844.   if(x < 0) 
  845.   { left += x;
  846.     width -= x;
  847.     x = 0;
  848.    }
  849.  
  850.   if(y < 0) 
  851.   { top += y;
  852.     height -= y;
  853.     y = 0;
  854.    }
  855.  
  856.   if(x+width > DISP_MAX_X) width = DISP_MAX_X - x;
  857.  
  858.   if(y+height > DISP_MAX_Y) height = DISP_MAX_Y - y;
  859.  
  860.   /* set write mode 1 */
  861.   port_out(5, GRA_I);
  862.   port_out(1, GRA_D);
  863.  
  864.   if (y <= top)
  865.   { first1 = VIDEO + LINE_BYTES*y + x/8;
  866.     last1  = VIDEO + LINE_BYTES*y + (x+width-1)/8;
  867.     first  = VIDEO + LINE_BYTES*top + left/8;
  868.     last   = VIDEO + LINE_BYTES*top + (left+width-1)/8;
  869.    }
  870.   else
  871.   { first1 = VIDEO + LINE_BYTES*(y+height-1) + x/8;
  872.     last1  = VIDEO + LINE_BYTES*(y+height-1) + (x+width-1)/8;
  873.     first  = VIDEO + LINE_BYTES*(top+height-1) + left/8;
  874.     last   = VIDEO + LINE_BYTES*(top+height-1) + (left+width-1)/8;
  875.    }
  876.  
  877.   for(i=0; i<height; i++)
  878.   { 
  879.     if (x <= left)
  880.       for(q=first, p=first1; q<=last; q++,p++) *p = *q;
  881.     else
  882.       for(q=last, p=last1; q>=first; q--,p--) *p = *q;
  883.  
  884.     if (y <= top)
  885.     { first1 += LINE_BYTES;
  886.       first  += LINE_BYTES;
  887.       last1  += LINE_BYTES;
  888.       last   += LINE_BYTES;
  889.      }
  890.     else
  891.     { first1 -= LINE_BYTES;
  892.       first  -= LINE_BYTES;
  893.       last1  -= LINE_BYTES;
  894.       last   -= LINE_BYTES;
  895.      }
  896.    }
  897.  
  898.   /* set write mode 0 */
  899.   port_out(5, GRA_I);
  900.   port_out(0, GRA_D);
  901.  
  902.  }
  903.  
  904. void copy_rect(Window w, int x1, int y1, int x2, int y2, int x, int y)
  905. { VgaWindow win = win_stack[w];
  906.   int width = x2-x1+1;
  907.   int height = y2-y1+1;
  908.   x1 += win->xpos; 
  909.   y1 += win->ypos; 
  910.   x  += win->xpos; 
  911.   y  += win->ypos; 
  912.   copy_box(x1,y1,width,height,x,y); 
  913.  }
  914.  
  915.  
  916. static char rev_byte(char c)
  917. { char c1 = 0x00;
  918.    for(int i=0; i<8; i++)
  919.    { c1 <<= 1;
  920.      if (c&1) c1 |= 1;
  921.      c >>= 1;
  922.     }
  923.   return c1;
  924. }
  925.  
  926.  
  927. void insert_bitmap(Window w, int width, int height, char* data)
  928. {
  929.   register VIDEO_PTR first;
  930.   register VIDEO_PTR last;
  931.   register VIDEO_PTR q;
  932.  
  933.   VgaWindow win = win_stack[w];
  934.  
  935.   int x = win->x0/8 + 1;
  936.   int y = win->ypos;
  937.  
  938.   int wi = (width > win->width) ? win->width : width;
  939.   int he = (height > win->height) ? win->height : height;
  940.  
  941.   first  = VIDEO + LINE_BYTES*y + x;
  942.   last   = VIDEO + LINE_BYTES*y + x + wi/8 - 1;
  943.  
  944.   if (width % 8)
  945.      width  = 1+ width/8;
  946.   else
  947.      width  = width/8;
  948.  
  949.   port_out(8, GRA_I);
  950.  
  951.   for(int i=0; i<he; i++)
  952.   { char* p = data + i*width;
  953.     for(q=first; q<=last; q++) 
  954.     { port_out(rev_byte(*p++), GRA_D);
  955.       *q = *q;
  956.      }
  957.     first += LINE_BYTES;
  958.     last  += LINE_BYTES;
  959.    }
  960.  }
  961.  
  962.